Flash 5 - Part 8: Movie-Clips &emp; GUI gadgets
Introduction
This article focuses on how to use the basic building blocks (ie. Movie-Clips, Buttons and action-scripting) to construct some bigger, but still simple GUI gadgets.
I learnt most of these techniques the hard way using Flash 4 and simply switched to function based actions in Flash 5. For most traditional programmers Flash can be a shock (wave) because there is no real 'mainloop' or sub-routine calls in the familiar sense. Instead it's best to approach your project like an event driven task (even your 'mainloop'). The code and ideas presented in the following article are (perhaps) not the most elegant in terms of Object Orientated Design (hey, I'm a die-hard assembly freak ;) but they work!
Remember to use [CTRL-E] for Expert-Mode to enter the actions.
A-B-C The order of creation?
Tip: When constructing a small component inside a larger container (eg. a button inside a movie-clip) do this:
(1) Draw a simple box
(2) Insert --> Convert To Symbol to create your component
(3) Edit the component to add all the detail.
I found this much easier than creating a new, blank symbol, drawing it and then dragging an Instance of it into the larger container. (The Convert To Symbol cuts the shape into a Symbol and automatically places an Instance where the shape was!)
Top-Down, or, Bottom-Up ?
There is no clear order to construct your component hierarchy in. You can work either way, in fact Flash helps to support both in its Convert To Symbol and Break Apart options. Remember that you can easily cut and paste between symbols using the Copy/Cut Frames and the normal Cut/Paste/Paste-In-Place functions.
Convert To Symbol
Note: If you have selected more than one layer then the Convert To Symbol option will 'flatten' your polygon shapes into a single layer. This means you might lose some transparency/layer effects because the overlapping shapes will be merged together. This is why I suggest drawing a simple (1 layer) shape, convert it and then edit it (adding layers effects etc...)
Break Apart
Drop-down menu
What we're aiming for is a button which when clicked brings up a menu, click it again and the menu disappears.
1) Place a Button Instance on the work-area
2) Select it and Convert To Symbol (Behavior: Movie-Clip, Name: 'Pop menu')
3) Using the Instance-panel, call it 'mcMenu'
4) Edit the Symbol (which is now a Button inside a Movie-Clip)
5) Insert KeyFrame (right-click Time-line menu)
You should have 2 KeyFrames on the Time-line, each frame has the Button Instance in it.
6) Draw a white box (or any other shape you want) on frame:2 under the Button.
7) Add a 'stop( )' action to frame:1
You can save and preview the Flash movie now (hit [CTRL-ENTER] ) and you will only see the button (the first frame of the movie-clip).
8) Go back to the 'Pop Menu' movie-clip and on frame:1 click on the Button Instance and add the following Object-Actions
// btw, these // lines are just comments! // you don't need to type them in ;-) // // actions for frame:1 button instance // on (release) { gotoAndStop (2); }
9) Go to frame:2 and add the following Object-Actions
// actions for frame:2 button instance // on (release) { gotoAndStop (1); }
Test the movie. If all goes well you will be able to open and close the menu by clicking on the button. As you can see we're toggling between frame:1 and frame:2 of our 'Pop Menu' using the gotoAndStop() action. Hey, I never said Flash was going to be difficult ;-)
Drop-down menu 2
1) Place a Button Instance on your stage/scene or 'work-area'
2) Draw a white box (or other such shape)
3) Select the shape and Convert To Symbol (Behaviour: Movie-Clip, Name:'Popski Menu')
4) Open the Instance-Panel and give the newly converted Symbol the Instance Name:'mcPop'
5) Edit the symbol (double-click)
6) On the Time-line drag the KeyFrame:1 to frame:2 (so you've created a blank frame at position:1)
7) Add a stop ( ) action on frame:1
8) Click on the 'Scene' (or double-click on the white, faded background)
9) Add the following Frame-Actions to frame:1 on the main, scene Time-line.
// Frame-Actions on main Scene time-line frame:1 // object.prototype.ToggleMenu = function(movieOBJ) { if (movieOBJ._currentframe != 1) { HideMenu(movieOBJ); } else { ShowMenu(movieOBJ); } } object.prototype.ShowMenu = function(movieOBJ) { movieOBJ.gotoAndStop(2); } object.prototype.HideMenu = function(movieOBJ) { movieOBJ.gotoAndStop(1); }
10) Add the following Object-Actions to the Button Instance.
// actions for button instance on (release) { ToggleMenu(mcPop); }
The result is the same as the first example, except we're passing the movie-clip object to our functions. The ToggleMenu( ) function examines the _currentframe property of the movie so it can tell the 'state' of it (frame:1 = hidden, frame:2 = show menu).
Animated menus
Tick-boxes
MainLoop:
Flash is limited to roughly ~200,000 operations per frame tick. If you want to perform some action over the course of any length of time, you need to split your action-scripting over more than one frame. This can seem crazy at first, but remember Flash wasn't really designed to be a programming environment, but an animation package with some 'simple' controls added on. The smallest 'MainLoop' possible is 2 frames. You can NOT loop on a single frame!
Simple Drag &emp; Drop
1) Place a Button Instance on the Stage.
2) Add these actions to the button
on (press) { startDrag (this); } on (release) { stopDrag (); }
2) Select the Button and Convert To Symbol (Behavior: Movie-Clip)
Easy huh?
Using Instances &emp; their names
As you already know Movie-Clip Instances can have their own, unique names which means they can be 'Target-ted' by using the path to them. If you have already tried to use 2 or more tick-boxes or other self-contained components then you might have found a problem. The idea of placing all the actions for a particular task inside one component (which can then be re-used by using multiple Instances of it) may seem like a good idea, and in most case it is. But how do you identify one tick-box from another tick-box? Remember the actions are identical.
The answer is simple, use the Instance name because is one of the few properties of each Instance which can be unique. The common action inside the 'component' (ie. Movie-Clip) can read its unique Instance name and process that as a parameter.
The following code Snippets (taken from the MENUS.FLA example Flash file) show how to read the Instance name and pass it to a common function. Normally this function would take the Instance name and use it to access some array to store the states of all the tick-boxes.
// proc: display the passed Instance name + flag // object.prototype.TickBoxClick = function(instname, flg) { _root.txtInfoBox = "Instance: "+instname+ " = "+flg; }
These actions should be attached to the 2 Button Instances (frame:1 and frame:2)
// Object-action for frame:1 Button on (release) { TickBoxClick(this._name, true); gotoAndStop (2); } // Object-action for frame:2 Button on (release) { TickBoxClick(this._name, false); gotoAndStop (1); }
States, Frames and Arrays
If you plan to revisit a user input form or to present some previously input data (such as passwords, tick-box states, preference settings etc..) then it's a very good idea to store their states in global variables such as an array, rather than relying on Text input fields or Movie-Clip frame states. One of the main reasons for doing this is that you can then access the data ANYWHERE including from within frames when those items aren't present.
// define a global array _root.TickBoxStates = new Array(10);
Goto and Jumps
Another 'quirk' of the Flash action-scripting which might catch out programmers is that the gotoAndPlay( ) and gotoAndStop( ) actions do NOT happen immediately! Flash stores the frame number until ALL the actions for a particular frame have been processed and then jumps to the new frame number. (Yes, Flash processes all the actions BEFORE rendering the graphics -- this allows you to control the current frame's appearance using the goto actions).
// Example of the goto quirk if (1==1) { gotoAndStop(2); } gotoAndStop(3);
The above code will always jump to frame 3. Remember, the goto actions control the frame numbers, NOT the action scriping location!!
Closing words
Phew, that was quite a long article, hope you kept up. If not, check out the supplied ZIP file for some examples.
Happy Scripting